#if defined(CB_PRECOMP)
#include "sdk.h"
#endif

#ifndef CB_PRECOMP
#include <wx/bmpbuttn.h>
#include <wx/combobox.h>
#include <wx/menu.h>
#include <wx/toolbar.h>
#include <wx/xrc/xmlres.h>

#include "configmanager.h"
#include "sdk_events.h"
#endif

#include "prep.h"
#include "cbstyledtextctrl.h"
#include "ThreadSearch.h"
#include "ThreadSearchView.h"
#include "ThreadSearchConfPanel.h"
#include "ThreadSearchControlIds.h"
#include "cbauibook.h"
#include "version.h"
#include "MainPanel.h"
#include "codesnippetsevent.h"
#include "snippetsconfig.h"
#include "scbeditor.h"
#include "seditormanager.h"
#include "editormanager.h"
#include "manager.h"


namespace {
  #if !wxCHECK_VERSION(3, 0, 0)

  int m_nSashSize = 2;
  #endif


}


int idEditUndo = XRCID("idEditUndo");
int idEditRedo = XRCID("idEditRedo");
int idEditCopy = XRCID("idEditCopy");
int idEditCut = XRCID("idEditCut");
int idEditPaste = XRCID("idEditPaste");
int idEditSwapHeaderSource = XRCID("idEditSwapHeaderSource");
int idEditGotoMatchingBrace = XRCID("idEditGotoMatchingBrace");
int idEditBookmarks = XRCID("idEditBookmarks");
int idEditBookmarksToggle = XRCID("idEditBookmarksToggle");
int idEditBookmarksPrevious = XRCID("idEditBookmarksPrevious");
int idEditBookmarksNext = XRCID("idEditBookmarksNext");
int idEditFoldAll = XRCID("idEditFoldAll");
int idEditUnfoldAll = XRCID("idEditUnfoldAll");
int idEditToggleAllFolds = XRCID("idEditToggleAllFolds");
int idEditFoldBlock = XRCID("idEditFoldBlock");
int idEditUnfoldBlock = XRCID("idEditUnfoldBlock");
int idEditToggleFoldBlock = XRCID("idEditToggleFoldBlock");
int idEditEOLCRLF = XRCID("idEditEOLCRLF");
int idEditEOLCR = XRCID("idEditEOLCR");
int idEditEOLLF = XRCID("idEditEOLLF");
int idEditEncoding = XRCID("idEditEncoding");
int idEditSelectAll = XRCID("idEditSelectAll");
int idEditCommentSelected = XRCID("idEditCommentSelected");
int idEditUncommentSelected = XRCID("idEditUncommentSelected");
int idEditToggleCommentSelected = XRCID("idEditToggleCommentSelected");
int idEditAutoComplete = XRCID("idEditAutoComplete");

int idMenuEditCopy = XRCID("idEditCopy");
int idMenuEditPaste = XRCID("idEditPaste");


BEGIN_EVENT_TABLE(ThreadSearch, cbPlugin)






  EVT_UPDATE_UI(idMenuSearchThreadSearch, ThreadSearch::OnMnuSearchThreadSearchUpdateUI)
  EVT_MENU(idMenuSearchThreadSearch, ThreadSearch::OnMnuSearchThreadSearch)
  EVT_MENU(idMenuCtxThreadSearch,    ThreadSearch::OnCtxThreadSearch)
  EVT_MENU(idMenuEditCopy,           ThreadSearch::OnMnuEditCopy)
  EVT_UPDATE_UI(idMenuEditCopy,           ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_MENU(idMenuEditPaste,          ThreadSearch::OnMnuEditPaste)
  EVT_BUTTON(idBtnOptions,             ThreadSearch::OnBtnOptionsClick)
  EVT_BUTTON(idBtnSearch,              ThreadSearch::OnBtnSearchClick)
  EVT_TEXT_ENTER(idCboSearchExpr,          ThreadSearch::OnCboSearchExprEnter)
  EVT_TEXT(idCboSearchExpr,          ThreadSearch::OnCboSearchExprEnter)
  EVT_SPLITTER_SASH_POS_CHANGED(wxID_ANY,  ThreadSearch::OnSashPositionChanged)

  EVT_CODESNIPPETS_NEW_INDEX(wxID_ANY,    ThreadSearch::OnCodeSnippetsNewIndex)









  EVT_UPDATE_UI(idEditUndo, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditRedo, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditCopy, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditCut, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditPaste, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditSwapHeaderSource, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditGotoMatchingBrace, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditFoldAll, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditUnfoldAll, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditToggleAllFolds, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditFoldBlock, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditUnfoldBlock, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditToggleFoldBlock, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditEOLCRLF, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditEOLCR, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditEOLLF, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditEncoding, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditSelectAll, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditBookmarksToggle, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditBookmarksNext, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditBookmarksPrevious, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditCommentSelected, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditAutoComplete, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditUncommentSelected, ThreadSearch::OnMnuEditCopyUpdateUI)
  EVT_UPDATE_UI(idEditToggleCommentSelected, ThreadSearch::OnMnuEditCopyUpdateUI)

END_EVENT_TABLE()


ThreadSearch::ThreadSearch(wxWindow* parent)

  : m_SearchedWord(wxEmptyString),
    m_pThreadSearchView(NULL),
    m_pViewManager(NULL),
    m_pToolbar(NULL),
    m_CtxMenuIntegration(true),
    m_UseDefValsForThreadSearch(true),
    m_ShowSearchControls(true),
    m_ShowDirControls(false),
    m_ShowCodePreview(true),
    m_LoggerType(ThreadSearchLoggerBase::TypeList),
    m_DisplayLogHeaders(true),
    m_DrawLogLines(false),
    m_pCboSearchExpr(0),
    m_SplitterMode(wxSPLIT_VERTICAL),
    m_FileSorting(InsertIndexManager::SortByFilePath) {
  m_pParent =  parent ;
  m_CodeSnippetsIndexFilename = wxEmptyString;
  GetConfig()->SetThreadSearchPlugin(this);
  m_EdNotebookSashPosition = 0;
  m_pMainPanel = 0;
  m_bSashWindowResizing = false;
}
ThreadSearch::~ThreadSearch() {
  GetConfig()->SetThreadSearchPlugin(0);
}

void ThreadSearch::OnAttach() {
  m_pThreadSearchViewParentBak = 0;
  m_pEdNotebookParentBak = 0;
  #if LOGGING
  LOGIT(_T("SnippetsSearch (ThreadSearch) Plugin Logging Started"));
  #endif
  bool showPanel;
  int  sashPosition;
  ThreadSearchViewManagerBase::eManagerTypes mgrType;
  wxArrayString searchPatterns;
  LoadConfig(showPanel, sashPosition, mgrType, searchPatterns);
  m_pThreadSearchView = new ThreadSearchView(*this);
  m_pThreadSearchView->SetSearchHistory(searchPatterns);
  m_pViewManager = ThreadSearchViewManagerBase::BuildThreadSearchViewManagerBase(m_pThreadSearchView, true, mgrType);
  m_pViewManager->ShowView(showPanel);
  int x, y;
  m_pThreadSearchView->GetSize(&x, &y);
  m_pThreadSearchView->SetSashPosition(x / 2);
  m_pThreadSearchView->Update();
  if(sashPosition != 0)
    m_pThreadSearchView->SetSashPosition(sashPosition);
  m_pThreadSearchView->ShowSearchControls(m_ShowSearchControls);
  m_pMainPanel = new MainPanel(m_pParent);
  m_pMainSplitter = m_pMainPanel->m_pSplitterWindow;
  m_pMainSplitter->SetMinimumPaneSize(20);
  m_pMainSizer = new wxBoxSizer(wxVERTICAL);
  m_pMainSizer->Add(m_pMainPanel, 1, wxEXPAND | wxALL, 1);
  m_pParent->SetSizer(m_pMainSizer);
  m_pParent->Layout();
  m_pThreadSearchViewParentBak = m_pThreadSearchView->GetParent();
  m_pThreadSearchView->SetWindowStyle(m_pThreadSearchView->GetWindowStyle() | wxSIMPLE_BORDER);
  m_pThreadSearchView->Reparent(m_pMainSplitter);
  m_pMainPanel->m_pSplitterWindow->ReplaceWindow(m_pMainPanel->m_pSearchPanel, m_pThreadSearchView);
  m_pMainPanel->m_pSearchPanel->Show(false);
  m_pEdNotebook = GetConfig()->GetEditorManager(m_pParent)->GetNotebook();
  {
    m_pEdNotebookParentBak = m_pEdNotebook->GetParent();
    m_pEdNotebook->SetWindowStyle(m_pEdNotebook->GetWindowStyle() | wxSIMPLE_BORDER);
    m_pEdNotebook->Reparent(m_pMainSplitter);
    m_pMainPanel->m_pSplitterWindow->ReplaceWindow(m_pMainPanel->m_pNotebkPanel, m_pEdNotebook);
    m_pMainPanel->m_pNotebkPanel->Show(false);
  }
  m_pMainPanel->m_pSplitterWindow->SetSashPosition(0);
  m_pMainPanel->m_pSplitterWindow->SetSashGravity(0.3);
  #if !wxCHECK_VERSION(3, 0, 0)
  m_pMainPanel->m_pSplitterWindow->SetSashSize(m_nSashSize);
  #endif
  m_pMainPanel->m_pSplitterWindow->Unsplit();
  if(sashPosition != 0)
    m_pThreadSearchView->SetSashPosition(sashPosition);
  int size = Manager::Get()->GetConfigManager(_T("message_manager"))->ReadInt(_T("/log_font_size"), platform::macosx ? 10 : 8);
  bool fixedPitchFont = true;
  wxFont default_font(size, fixedPitchFont ? wxFONTFAMILY_MODERN : wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
  m_Conf_font = default_font;
  m_OnReleased = false;
}

void ThreadSearch::OnRelease(bool) {
  if(m_OnReleased)
    return;
  m_OnReleased = true;
  if(m_pThreadSearchViewParentBak) {
    m_pThreadSearchView->Reparent(m_pThreadSearchViewParentBak);
    m_pMainPanel->m_pSplitterWindow->ReplaceWindow(m_pThreadSearchView, m_pMainPanel->m_pSearchPanel);
  }
  if(m_pEdNotebookParentBak) {
    m_pEdNotebook->Reparent(m_pEdNotebookParentBak);
    m_pMainPanel->m_pSplitterWindow->ReplaceWindow(m_pEdNotebook, m_pMainPanel->m_pNotebkPanel);
  }
  if(m_pMainPanel)
    m_pMainPanel->Destroy();
  RemoveMenuItems();
  m_pToolbar = NULL;
  if(m_pThreadSearchView != NULL) {
    m_pViewManager->RemoveViewFromManager();
    m_pThreadSearchView->Destroy();
  }
  delete m_pViewManager;
  m_pViewManager = NULL;
}


void ThreadSearch::OnThreadSearchViewDestruction() {
  m_pThreadSearchView->ApplySplitterSettings(m_ShowCodePreview, m_SplitterMode);
  SaveConfig(m_pViewManager->IsViewShown(),
             m_pThreadSearchView->GetSashPosition(),
             m_pViewManager->GetManagerType(),
             m_pThreadSearchView->GetSearchHistory());
  m_pThreadSearchView = NULL;
}


void ThreadSearch::BuildMenu(wxMenuBar* menuBar) {
  size_t i;
  int idx = menuBar->FindMenu(_("&View"));
  if(idx != wxNOT_FOUND) {
    wxMenu* menu = menuBar->GetMenu(idx);
    wxMenuItemList& items = menu->GetMenuItems();
    for(i = 0; i < items.GetCount(); ++i) {
      if(items[i]->IsSeparator()) {
        menu->Insert(i, idMenuViewThreadSearch, wxT("Snippets search"),
                     wxT("Toggle displaying the 'Snippets search' panel"));
        break;
      }
    }
    if(i == items.GetCount()) {
      menu->Append(idMenuViewThreadSearch, wxT("Snippets search"),
                   wxT("Toggle displaying the 'Snippets search' panel"));
    }
  }
  idx = menuBar->FindMenu(_("Sea&rch"));
  if(idx != wxNOT_FOUND) {
    wxMenu* menu = menuBar->GetMenu(idx);
    wxMenuItemList& items = menu->GetMenuItems();
    for(i = 0; i < items.GetCount(); ++i) {
      if(items[i]->IsSeparator())
        break;
    }
    if(i == items.GetCount()) {
    }
  }
}

void ThreadSearch::RemoveMenuItems() {
  wxMenuBar* menuBar = Manager::Get()->GetAppFrame()->GetMenuBar();
  int idx = menuBar->FindMenu(_("&View"));
  if(idx != wxNOT_FOUND) {
    wxMenu* viewMenu = menuBar->GetMenu(idx);
    if(viewMenu != NULL)
      viewMenu->Remove(idMenuViewThreadSearch);
  }
  idx = menuBar->FindMenu(_("Sea&rch"));
  if(idx != wxNOT_FOUND) {
    wxMenu* searchMenu = menuBar->GetMenu(idx);
    if(searchMenu != NULL)
      searchMenu->Remove(idMenuSearchThreadSearch);
  }
}


void ThreadSearch::OnMnuViewThreadSearch(wxCommandEvent& event) {
  if(!IsAttached())
    return;
  m_pViewManager->ShowView(event.IsChecked());
}


void ThreadSearch::OnMnuSearchThreadSearch(wxCommandEvent& WXUNUSED(event)) {
  if(!IsAttached())
    return;
  if((GetCursorWord(m_SearchedWord) == true) && (m_SearchedWord.IsEmpty() == false))
    RunThreadSearch(m_SearchedWord, true);
  else
    m_pViewManager->ShowView(true);
}


void ThreadSearch::OnCtxThreadSearch(wxCommandEvent& WXUNUSED(event)) {
  if(!IsAttached())
    return;
  RunThreadSearch(m_SearchedWord, true);
}


void ThreadSearch::OnMnuViewThreadSearchUpdateUI(wxUpdateUIEvent& WXUNUSED(event)) {
  return;
  if(!IsAttached())
    return;
  Manager::Get()->GetAppFrame()->GetMenuBar()->Check(idMenuViewThreadSearch, m_pViewManager->IsViewShown());
}

void ThreadSearch::OnMnuSearchThreadSearchUpdateUI(wxUpdateUIEvent& event) {
  if(!IsAttached())
    return;
  event.Enable(m_pThreadSearchView->IsSearchRunning() == false);
}

void ThreadSearch::BuildModuleMenu(const ModuleType type, wxMenu* pMenu, const FileTreeData*) {
  wxMenuItem* pMenuItem = NULL;
  if(!pMenu || !IsAttached())
    return;
  if((type == mtEditorManager) && (m_CtxMenuIntegration == true)) {
    if(GetCursorWord(m_SearchedWord) == true) {
      wxString srchString = m_SearchedWord.Mid(0, 16);
      if(m_SearchedWord.Length() > 16)
        srchString << _T("...");
      wxString sText = wxT("Find occurrences of: '") + srchString + wxT("'");
      int dIndex = GetInsertionMenuIndex(pMenu);
      if(dIndex >= 0)
        pMenuItem = pMenu->Insert(dIndex, idMenuCtxThreadSearch, sText);
      else {
        pMenu->AppendSeparator();
        pMenuItem = pMenu->Append(idMenuCtxThreadSearch, sText);
      }
      pMenuItem->Enable(!m_pThreadSearchView->IsSearchRunning());
    }
  }
}



int ThreadSearch::GetInsertionMenuIndex(const wxMenu* const pCtxMenu) {
  if(!IsAttached())
    return -1;
  const wxMenuItemList ItemsList = pCtxMenu->GetMenuItems();
  for(int i = 0; i < (int)ItemsList.GetCount(); ++i) {
    #if wxCHECK_VERSION(3, 0, 0)
    if(ItemsList[i]->GetItemLabelText().StartsWith(_T("Find implementation of:")))
    #else
    if(ItemsList[i]->GetLabel().StartsWith(_T("Find implementation of:")))
    #endif
    {
      return ++i;
    }
  }
  return -1;
}



cbConfigurationPanel* ThreadSearch::GetConfigurationPanel(wxWindow* parent) {
  if(!IsAttached())
    return NULL;
  return new ThreadSearchConfPanel(*this, parent);
}


void ThreadSearch::Notify() {
  if(!IsAttached())
    return;
  m_pThreadSearchView->Clear();
  m_pThreadSearchView->Update();
  SaveConfig(m_pViewManager->IsViewShown(),
             m_pThreadSearchView->GetSashPosition(),
             m_pViewManager->GetManagerType(),
             m_pThreadSearchView->GetSearchHistory());
  if(m_FindData.MustSearchInProject() == true) {
    CodeSnippetsEvent evt(wxEVT_CODESNIPPETS_GETFILELINKS, 0);
    evt.ProcessCodeSnippetsEvent(evt);
  } else
    GetConfig()->GetFileLinksMapArray().clear();
}


void ThreadSearch::LoadConfig(bool& showPanel, int& sashPosition,

                              ThreadSearchViewManagerBase::eManagerTypes& mgrType,
                              wxArrayString& searchPatterns) {
  if(!IsAttached())
    return;
  ConfigManager* pCfg = Manager::Get()->GetConfigManager(_T("SnippetsSearch"));
  m_FindData.SetMatchWord(pCfg->ReadBool(wxT("/MatchWord"),          true));
  m_FindData.SetStartWord(pCfg->ReadBool(wxT("/StartWord"),          false));
  m_FindData.SetMatchCase(pCfg->ReadBool(wxT("/MatchCase"),          true));
  m_FindData.SetRegEx(pCfg->ReadBool(wxT("/RegEx"),              false));
  m_FindData.SetHiddenSearch(pCfg->ReadBool(wxT("/HiddenSearch"),       true));
  m_FindData.SetRecursiveSearch(pCfg->ReadBool(wxT("/RecursiveSearch"),    true));
  m_CtxMenuIntegration         = pCfg->ReadBool(wxT("/CtxMenuIntegration"), true);
  m_UseDefValsForThreadSearch  = pCfg->ReadBool(wxT("/UseDefaultValues"),   true);
  m_ShowSearchControls         = pCfg->ReadBool(wxT("/ShowSearchControls"), true);
  m_ShowDirControls            = pCfg->ReadBool(wxT("/ShowDirControls"),    false);
  m_ShowCodePreview            = pCfg->ReadBool(wxT("/ShowCodePreview"),    true);
  m_DisplayLogHeaders          = pCfg->ReadBool(wxT("/DisplayLogHeaders"),  true);
  m_DrawLogLines               = pCfg->ReadBool(wxT("/DrawLogLines"),       false);
  showPanel                    = pCfg->ReadBool(wxT("/ShowPanel"),          true);
  m_FindData.SetScope(pCfg->ReadInt(wxT("/Scope"),              ScopeSnippetFiles));
  m_FindData.SetSearchPath(pCfg->Read(wxT("/DirPath"),            wxEmptyString));
  m_FindData.SetSearchMask(pCfg->Read(wxT("/Mask"),               wxT("*.cpp;*.c;*.h")));
  sashPosition                 = pCfg->ReadInt(wxT("/SplitterPosn"),        0);
  int splitterMode             = pCfg->ReadInt(wxT("/SplitterMode"),        wxSPLIT_VERTICAL);
  m_SplitterMode               = wxSPLIT_VERTICAL;
  if(splitterMode == wxSPLIT_HORIZONTAL)
    m_SplitterMode = wxSPLIT_HORIZONTAL;
  int managerType              = pCfg->ReadInt(wxT("/ViewManagerType"),     ThreadSearchViewManagerBase::TypeMessagesNotebook);
  mgrType                      = ThreadSearchViewManagerBase::TypeMessagesNotebook;
  if(managerType == ThreadSearchViewManagerBase::TypeLayout)
    mgrType = ThreadSearchViewManagerBase::TypeLayout;
  int loggerType               = pCfg->ReadInt(wxT("/LoggerType"),          ThreadSearchLoggerBase::TypeList);
  m_LoggerType                 = ThreadSearchLoggerBase::TypeList;
  if(loggerType == ThreadSearchLoggerBase::TypeTree)
    m_LoggerType = ThreadSearchLoggerBase::TypeTree;
  searchPatterns = pCfg->ReadArrayString(wxT("/SearchPatterns"));
}

void ThreadSearch::SaveConfig(bool showPanel, int sashPosition,
                              ThreadSearchViewManagerBase::eManagerTypes,
                              const wxArrayString& searchPatterns) {
  ConfigManager* pCfg = Manager::Get()->GetConfigManager(_T("SnippetsSearch"));
  pCfg->Write(wxT("/MatchWord"),          m_FindData.GetMatchWord());
  pCfg->Write(wxT("/StartWord"),          m_FindData.GetStartWord());
  pCfg->Write(wxT("/MatchCase"),          m_FindData.GetMatchCase());
  pCfg->Write(wxT("/RegEx"),              m_FindData.GetRegEx());
  pCfg->Write(wxT("/HiddenSearch"),       m_FindData.GetHiddenSearch());
  pCfg->Write(wxT("/RecursiveSearch"),    m_FindData.GetRecursiveSearch());
  pCfg->Write(wxT("/CtxMenuIntegration"), m_CtxMenuIntegration);
  pCfg->Write(wxT("/UseDefaultValues"),   m_UseDefValsForThreadSearch);
  pCfg->Write(wxT("/ShowSearchControls"), m_ShowSearchControls);
  pCfg->Write(wxT("/ShowDirControls"),    m_ShowDirControls);
  pCfg->Write(wxT("/ShowCodePreview"),    m_ShowCodePreview);
  pCfg->Write(wxT("/DisplayLogHeaders"),  m_DisplayLogHeaders);
  pCfg->Write(wxT("/DrawLogLines"),       m_DrawLogLines);
  pCfg->Write(wxT("/ShowPanel"),          showPanel);
  pCfg->Write(wxT("/Scope"),              m_FindData.GetScope());
  pCfg->Write(wxT("/DirPath"),            m_FindData.GetSearchPath());
  pCfg->Write(wxT("/Mask"),               m_FindData.GetSearchMask());
  pCfg->Write(wxT("/SplitterPosn"),       sashPosition);
  pCfg->Write(wxT("/SplitterMode"), (int)m_SplitterMode);
  pCfg->Write(wxT("/ViewManagerType"),    m_pViewManager->GetManagerType());
  pCfg->Write(wxT("/LoggerType"),         m_LoggerType);
  pCfg->Write(wxT("/FileSorting"),        m_FileSorting);
  pCfg->Write(wxT("/SearchPatterns"),     searchPatterns);
}

bool ThreadSearch::BuildToolBar(wxToolBar* toolBar) {
  if(!IsAttached() || !toolBar)
    return false;
  m_pToolbar = toolBar;
  m_pThreadSearchView->SetToolBar(toolBar);
  wxString prefix                = ConfigManager::GetDataFolder() + _T("/images/codesnippets/");
  m_pCboSearchExpr               = new wxComboBox(toolBar, idCboSearchExpr, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);
  wxBitmapButton* pBtnSearch     = new wxBitmapButton(toolBar, idBtnSearch, wxBitmap(prefix + wxT("findf.png"), wxBITMAP_TYPE_PNG));
  wxBitmapButton* pBtnOptions    = new wxBitmapButton(toolBar, idBtnOptions, wxBitmap(prefix + wxT("options.png"), wxBITMAP_TYPE_PNG));
  m_pCboSearchExpr->SetToolTip(wxT("Text to search"));
  pBtnSearch->SetToolTip(wxT("Run search"));
  pBtnOptions->SetToolTip(wxT("Show options window"));
  pBtnSearch->SetBitmapDisabled(wxBitmap(prefix + wxT("findfdisabled.png"), wxBITMAP_TYPE_PNG));
  pBtnOptions->SetBitmapDisabled(wxBitmap(prefix + wxT("optionsdisabled.png"), wxBITMAP_TYPE_PNG));
  toolBar->AddControl(m_pCboSearchExpr);
  toolBar->AddControl(pBtnSearch);
  toolBar->AddControl(pBtnOptions);
  toolBar->Realize();
  toolBar->SetInitialSize();
  return true;
}

void ThreadSearch::OnBtnOptionsClick(wxCommandEvent &event) {
  if(!IsAttached())
    return;
  m_pThreadSearchView->ProcessEvent(event);
}


void ThreadSearch::OnBtnSearchClick(wxCommandEvent &event) {
  if(!IsAttached())
    return;
  if(m_pThreadSearchView->IsSearchRunning())
    m_pThreadSearchView->ProcessEvent(event);
  else {
    wxComboBox* pCboBox = static_cast<wxComboBox*>(m_pToolbar->FindControl(idCboSearchExpr));
    wxASSERT(pCboBox != NULL);
    RunThreadSearch(pCboBox->GetValue());
  }
}

void ThreadSearch::RunThreadSearch(const wxString& text, bool isCtxSearch) {
  if(!IsAttached())
    return;
  ThreadSearchFindData findData = m_FindData;
  if((isCtxSearch == true) && (m_UseDefValsForThreadSearch == true)) {
    findData.SetMatchCase(true);
    findData.SetMatchWord(true);
    findData.SetStartWord(false);
    findData.SetRegEx(false);
  }
  findData.SetFindText(text);
  m_pViewManager->ShowView(true);
  m_pThreadSearchView->ThreadedSearch(findData);
}


void ThreadSearch::OnCboSearchExprEnter(wxCommandEvent &event) {
  if(!IsAttached())
    return;
  wxComboBox* pCboBox = static_cast<wxComboBox*>(m_pToolbar->FindControl(idCboSearchExpr));
  wxASSERT(pCboBox != NULL);
  if(event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
    RunThreadSearch(pCboBox->GetValue());
}


void ThreadSearch::ShowToolBar(bool show) {
  if(!IsAttached())
    return;
  bool isShown = IsWindowReallyShown(m_pToolbar);
  if(show != isShown) {
    CodeBlocksDockEvent evt(show ? cbEVT_SHOW_DOCK_WINDOW : cbEVT_HIDE_DOCK_WINDOW);
    evt.pWindow = (wxWindow*)m_pToolbar;
    evt.shown = show;
  }
}


bool ThreadSearch::IsToolbarVisible() {
  if(!IsAttached())
    return false;
  return IsWindowReallyShown(m_pToolbar);
}

bool ThreadSearch::GetCursorWord(wxString& sWord) {
  bool wordFound = false;
  sWord = wxEmptyString;
  ScbEditor* ed = GetConfig()->GetEditorManager(m_pParent)->GetBuiltinActiveEditor();
  if(ed != NULL) {
    cbStyledTextCtrl* control = ed->GetControl();
    int pos = control->GetCurrentPos();
    int ws  = control->WordStartPosition(pos, true);
    int we  = control->WordEndPosition(pos, true);
    if(ws < we) {
      sWord = control->GetTextRange(ws, we);
      wordFound = true;
    }
    const wxString selectedText = control->GetSelectedText();
    if(not selectedText.IsEmpty()) {
      sWord = selectedText;
      wordFound = true;
    }
  }
  return wordFound;
}


void ThreadSearch::OnMnuEditCopy(wxCommandEvent& event) {
  if(!IsAttached()) {
    event.Skip();
    return;
  }
  wxWindow* pFocused = wxWindow::FindFocus();
  if(pFocused == m_pCboSearchExpr) {
    if(m_pCboSearchExpr->CanCopy())
      m_pCboSearchExpr->Copy();
    LOGIT(_T("OnMnuEditcopy for m_pCboSearchExpr"));
  } else if(pFocused == m_pThreadSearchView->m_pCboSearchExpr) {
    if(m_pThreadSearchView->m_pCboSearchExpr->CanCopy())
      m_pThreadSearchView->m_pCboSearchExpr->Copy();
    LOGIT(_T("OnMnuEditcopy for m_pThreadSearchView->m_pCboSearchExpr"));
  } else if(pFocused == static_cast<wxWindow*>(m_pThreadSearchView->m_pSearchPreview)) {
    bool hasSel = m_pThreadSearchView->m_pSearchPreview->GetSelectionStart() != m_pThreadSearchView->m_pSearchPreview->GetSelectionEnd();
    if(hasSel)
      m_pThreadSearchView->m_pSearchPreview->Copy();
    LOGIT(_T("OnMnuEditcopy for m_pSearchPreview"));
  } else
    event.Skip();
  return;
}


void ThreadSearch::OnMnuEditCopyUpdateUI(wxUpdateUIEvent& event) {
  if(!IsAttached()) {
    event.Skip();
    return;
  }
  wxWindow* pFocused = wxWindow::FindFocus();
  if(not pFocused)
    return;
  wxMenuBar* mbar = Manager::Get()->GetAppFrame()->GetMenuBar();
  if(not mbar)
    return;
  bool hasSel = false;
  if(pFocused == m_pCboSearchExpr)
    hasSel =  m_pCboSearchExpr->CanCopy() ;
  else if(pFocused == m_pThreadSearchView->m_pCboSearchExpr)
    hasSel = m_pThreadSearchView->m_pCboSearchExpr->CanCopy();
  else if(pFocused == static_cast<wxWindow*>(m_pThreadSearchView->m_pSearchPreview))
    hasSel = m_pThreadSearchView->m_pSearchPreview->GetSelectionStart() != m_pThreadSearchView->m_pSearchPreview->GetSelectionEnd();
  if(hasSel) {
    mbar->Enable(idMenuEditCopy, hasSel);
    wxToolBar* pMainToolBar = (wxToolBar*) ::wxFindWindowByName(wxT("toolbar"), NULL);
    if(pMainToolBar)
      pMainToolBar->EnableTool(idMenuEditCopy, hasSel);
    return;
  }
  event.Skip();
  return;
}

void ThreadSearch::OnMnuEditPaste(wxCommandEvent& event) {
  if(!IsAttached())
  { event.Skip(); return; }
  if(not m_IsAttached) {
    event.Skip();
    return;
  }
  wxWindow* pFocused = wxWindow::FindFocus();
  if(not pFocused) {
    event.Skip();
    return;
  }
  wxString focusedStr = pFocused->GetName();
  if((pFocused == m_pThreadSearchView->m_pSearchPreview) ||
      (pFocused == (wxWindow*)m_pThreadSearchView->m_pLogger))
    return;
  if((pFocused != m_pCboSearchExpr)
      && (pFocused != m_pThreadSearchView->m_pCboSearchExpr))
  { event.Skip(); return;}
  if(pFocused == m_pCboSearchExpr)
    m_pCboSearchExpr->Paste();
  if(pFocused == m_pThreadSearchView->m_pCboSearchExpr)
    m_pThreadSearchView->m_pCboSearchExpr->Paste();
  return;
}

void ThreadSearch::SetManagerType(ThreadSearchViewManagerBase::eManagerTypes mgrType) {
  if(mgrType != m_pViewManager->GetManagerType()) {
    bool show(true);
    if(m_pViewManager != NULL) {
      show = m_pViewManager->IsViewShown();
      m_pViewManager->RemoveViewFromManager();
      delete m_pViewManager;
    }
    m_pViewManager = ThreadSearchViewManagerBase::BuildThreadSearchViewManagerBase(m_pThreadSearchView, true, mgrType);
    m_pViewManager->ShowView(show);
  }
}

void ThreadSearch::UserResizingWindow(wxSizeEvent & WXUNUSED(event)) {
  #if defined(LOGGING)
  #endif
  if(m_pMainPanel && m_pMainPanel->m_pSplitterWindow && m_pThreadSearchView && m_pEdNotebook)
    if(m_pMainPanel->m_pSplitterWindow->IsSplit()) {
      #if defined(LOGGING)
      #endif
      m_bSashWindowResizing = true;
    }
  return;
}

void ThreadSearch::OnSashPositionChanged(wxSplitterEvent& event) {
  if(m_OnReleased)
    return;
  #if defined(LOGGING)
  #endif
  if(not m_bSashWindowResizing) {
    m_EdNotebookSashPosition = event.GetSashPosition();
    event.Skip();
  }
  if(m_bSashWindowResizing) {
    m_bSashWindowResizing = false;
    ResetNotebookSashPosition();
  }
}

void ThreadSearch::OnIdle(wxIdleEvent& event) {
  if(m_OnReleased)
    return;
  if(m_bSashPositionChanged) {
    #if !wxCHECK_VERSION(3, 0, 0)
    m_pMainPanel->m_pSplitterWindow->SetSashSize(m_nSashSize);
    #endif
    m_pMainPanel->m_pSplitterWindow->Refresh();
    m_bSashPositionChanged = false;
    #if defined(LOGGING)
    LOGIT(_T("ThreadSearch:OnIdle:"));
    #endif
  }
  event.Skip();
}

void ThreadSearch::OnCodeSnippetsNewIndex(CodeSnippetsEvent& event) {
  wxString newIndex = event.GetSnippetString();
  do {
    if(newIndex.IsEmpty())
      break;
    if(not m_CodeSnippetsIndexFilename.IsEmpty()) {
      GetConfig()->GetEditorManager(m_pParent)->Close(m_CodeSnippetsIndexFilename);
      m_pThreadSearchView->Clear();
    }
    m_CodeSnippetsIndexFilename = newIndex;
    if(m_FindData.MustSearchInCodeSnippetsTree() == true) {
      CodeSnippetsEvent evt(wxEVT_CODESNIPPETS_GETFILELINKS, 0);
      evt.SetSnippetString(_T("Testing GetFileLinks"));
      evt.ProcessCodeSnippetsEvent(evt);
    } else
      GetConfig()->ClearFileLinksMapArray();
    #if defined(LOGGING)
    LOGIT(_T("ThreadSearch::OnCodeSnippetsNewIndex[%s]"), m_CodeSnippetsIndexFilename.c_str());
    #endif
  } while(false);
  event.Skip();
  return;
}

void ThreadSearch::SplitThreadSearchWindow() {
  if(m_pMainPanel && m_pMainPanel->m_pSplitterWindow && m_pThreadSearchView && m_pEdNotebook)
    if(not m_pMainPanel->m_pSplitterWindow->IsSplit()) {
      m_pMainPanel->m_pSplitterWindow->SplitHorizontally(
        m_pThreadSearchView, (wxWindow*)m_pEdNotebook);
      if(m_EdNotebookSashPosition)
        m_pMainPanel->m_pSplitterWindow->SetSashPosition(m_EdNotebookSashPosition);
      else {
        int sashPosn = m_pMainPanel->m_pSplitterWindow->GetSashPosition();
        ConfigManager* pCfg = Manager::Get()->GetConfigManager(_T("SnippetsSearch"));
        m_EdNotebookSashPosition = pCfg->ReadInt(wxT("/EdNotebookSashPosn"), sashPosn);
        m_pMainPanel->m_pSplitterWindow->SetSashPosition(m_EdNotebookSashPosition);
      }
    }
}

void ThreadSearch::ResetNotebookSashPosition() {
  if(m_pMainPanel && m_pMainPanel->m_pSplitterWindow && m_pThreadSearchView && m_pEdNotebook)
    if(m_pMainPanel->m_pSplitterWindow->IsSplit()) {
      if(m_EdNotebookSashPosition)
        m_pMainPanel->m_pSplitterWindow->SetSashPosition(m_EdNotebookSashPosition);
    }
}

void ThreadSearch::UnsplitThreadSearchWindow() {
  if(m_pMainPanel && m_pMainPanel->m_pSplitterWindow && m_pThreadSearchView && m_pEdNotebook)
    if(m_pMainPanel->m_pSplitterWindow->IsSplit()) {
      m_EdNotebookSashPosition = m_pMainPanel->m_pSplitterWindow->GetSashPosition();
      ConfigManager* pCfg = Manager::Get()->GetConfigManager(_T("SnippetsSearch"));
      pCfg->Write(wxT("/EdNotebookSashPosn"), m_EdNotebookSashPosition);
      m_pMainPanel->m_pSplitterWindow->Unsplit();
    }
}

